package dk.degofedal.scala.math

class Rational private(val n: Int, val d: Int) {
  
  require(d != 0)
  
  def / (R: Rational) = Rational(n * R.d, d * R.n)
  def \ (R: Rational) = Rational(n * R.d, d * R.n)
  def / (x: Int) = Rational(n, d * x)
  def \ (x: Int) = Rational(n, d * x)
  
  def * (R: Rational) = Rational(n * R.n, d * R.d)
  def + (R: Rational) = Rational(n * R.d + d * R.n, d * R.d)
  def - (R: Rational) = Rational(n * R.d - d * R.n, d * R.d)
  
  def < (R: Rational) = n * R.d < R.n * d
  def <= (R: Rational) = n * R.d <= R.n * d
  def > (R: Rational) = n * R.d > R.n * d
  def >= (R: Rational) = n * R.d >= R.n * d
  def == (R: Rational) = n * R.d == R.n * d
  
  def max(R: Rational) = if (this > R) this else R
  def min(R: Rational) = if (this < R) this else R
  
  override def toString = n + "/" + d
}

object Rational {
  
  def apply(n: Int) = new Rational(n, 1)
  
  def apply(n: Int, d: Int) = {
    val g = gcd(n abs ,d abs)
    new Rational(n / g, d / g)
  }
  
  private def gcd(x:Int, y:Int):Int = {
    if(y == 0) {
      x
    } else {
      gcd(y, x % y)
    }
  }
  
  implicit def rationalWrapper(x: Int) = new Rational(x, 1)
  
}